import { z } from 'zod';

/**
 * 应用配置Schema定义
 */
const ConfigSchema = z.object({
  server: z.object({
    port: z.coerce.number().int().positive().default(3000),
    host: z.string().default('0.0.0.0'),
    logLevel: z.enum(['fatal', 'error', 'warn', 'info', 'debug', 'trace']).default('info')
  }),
  mongodb: z.object({
    host: z.string(),
    port: z.coerce.number().int().positive(),
    database: z.string(),
    user: z.string().optional(),
    password: z.string().optional(),
    uri: z.string().optional()
  }),
  redis: z.object({
    host: z.string().default('localhost'),
    port: z.coerce.number().int().positive().default(6379),
    password: z.string().optional(),
    maxRetriesPerRequest: z.coerce.number().int().positive().default(3)
  }),
  rabbitmq: z.object({
    host: z.string().default('localhost'),
    port: z.coerce.number().int().positive().default(5672),
    user: z.string().optional(),
    password: z.string().optional(),
    exchange: z.string().default('mcp.messages')
  }),
  ai: z.object({
    deepseekApiKey: z.string().optional(),
    openaiApiKey: z.string().optional(),
    defaultModel: z.string().default('deepseek-chat')
  }),
  security: z.object({
    corsOrigin: z.string().default('*'),
    rateLimitMax: z.coerce.number().int().positive().default(1000),
    rateLimitWindow: z.string().default('1 minute')
  })
});

export type MCPConfig = z.infer<typeof ConfigSchema>;

/**
 * 配置加载器类
 */
export class ConfigLoader {
  private static instance: MCPConfig | null = null;

  /**
   * 加载和验证应用配置
   */
  static load(): MCPConfig {
    if (this.instance) {
      return this.instance;
    }

    const config = {
      server: {
        port: process.env['PORT'] || '3000',
        host: process.env['HOST'] || '0.0.0.0',
        logLevel: (process.env['LOG_LEVEL'] as any) || 'info'
      },
      mongodb: {
        host: process.env['MONGODB_HOST'] || 'localhost',
        port: process.env['MONGODB_PORT'] || '27017',
        database: process.env['MONGODB_DATABASE'] || 'sker-ai',
        user: process.env['MONGODB_ROOT_USER'],
        password: process.env['MONGODB_ROOT_PASSWORD'],
        uri: process.env['MONGODB_URI']
      },
      redis: {
        host: process.env['REDIS_HOST'] || 'localhost',
        port: process.env['REDIS_PORT'] || '6379',
        password: process.env['REDIS_PASSWORD'],
        maxRetriesPerRequest: process.env['REDIS_MAX_RETRIES'] || '3'
      },
      rabbitmq: {
        host: process.env['RABBITMQ_HOST'] || 'localhost',
        port: process.env['RABBITMQ_PORT'] || '5672',
        user: process.env['RABBITMQ_DEFAULT_USER'],
        password: process.env['RABBITMQ_DEFAULT_PASS'],
        exchange: process.env['RABBITMQ_EXCHANGE'] || 'mcp.messages'
      },
      ai: {
        deepseekApiKey: process.env['DEEPSEEK_SK'],
        openaiApiKey: process.env['OPENAI_API_KEY'],
        defaultModel: process.env['AI_DEFAULT_MODEL'] || 'deepseek-chat'
      },
      security: {
        corsOrigin: process.env['CORS_ORIGIN'] || '*',
        rateLimitMax: process.env['RATE_LIMIT_MAX'] || '1000',
        rateLimitWindow: process.env['RATE_LIMIT_WINDOW'] || '1 minute'
      }
    };

    try {
      this.instance = ConfigSchema.parse(config);
      return this.instance;
    } catch (error) {
      if (error instanceof z.ZodError) {
        console.error('配置验证失败:', error.issues);
        throw new Error(`配置验证失败: ${error.issues.map((e) => `[${e.path.join('.')}] ${e.message}`).join('; ')}`);
      }
      throw error;
    }
  }

  /**
   * 获取已加载的配置实例
   */
  static getInstance(): MCPConfig {
    if (!this.instance) {
      throw new Error('配置尚未加载，请先调用 ConfigLoader.load()');
    }
    return this.instance;
  }

  /**
   * 清除配置缓存（主要用于测试）
   */
  static clearInstance(): void {
    this.instance = null;
  }
}
